﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.DirectoryServices;
using System.Data;
using System.Configuration;
using System.Text;

namespace SAICAPPWEB.Common
{
    public class SynchronousAD
    {
        public List<AdModel> GetUser(string dc = "smc")
        {
            list.Clear();
            string DomainName = string.Format("10.90.9.185/DC={0},DC=saicmotor,DC=com", dc);
            string UserName = "smc\\changhaif";
            string Pwd = "Password1234";
            string RootUserOUName = string.Empty;
            if (dc.ToLower() == "smc")
                RootUserOUName = string.Format("{0} User", dc.ToUpper());
            else
                RootUserOUName = string.Format("{0}_Users", dc.ToUpper());

            DirectoryEntry domain;
            DirectoryEntry rootOU;
            if (IsConnected(DomainName.Trim(), UserName.Trim(), Pwd.Trim(), out domain))
            {
                if (IsExistOU(domain, out rootOU, RootUserOUName))
                {
                    SyncAll(rootOU);      //同步所有                                         
                }
                else
                {
                    LogHelper.Error("域中不存在此组织结构!" + RootUserOUName);
                    return list;
                }
                return list;
            }
            return list;
        }
        public List<AdModel> GetGroup(string dc = "smc")
        {
            list.Clear();
            string DomainName = "10.90.9.185/DC=smc,DC=saicmotor,DC=com";
            string UserName = "smc\\changhaif";
            string Pwd = "Password1234";
            string RootGroupOUName = string.Format("{0}_Groups", dc.ToUpper());
            DirectoryEntry domain;
            DirectoryEntry rootOU;
            if (IsConnected(DomainName.Trim(), UserName.Trim(), Pwd.Trim(), out domain))
            {
                //同步组
                if (IsExistOU(domain, out rootOU, RootGroupOUName))
                {
                    SyncAll(rootOU);      //同步所有                                         
                }
                else
                {
                    LogHelper.Error("域中不存在此组织结构!" + RootGroupOUName);
                    return list;
                }
                return list;

            }
            return list;

        }
        private List<AdModel> list = new List<AdModel>();
        #region## 同步
        /// <summary>
        /// 功能:同步
        /// 创建人:Wilson
        /// 创建时间:2012-12-15
        /// </summary>
        /// <param name="entryOU"></param>
        private void SyncAll(DirectoryEntry entryOU)
        {
            /*
             * 参考：http://msdn.microsoft.com/zh-cn/library/system.directoryservices.directorysearcher.filter(v=vs.80).aspx
             * 
             * -----------------其它------------------------------             
             * 机算机：       (objectCategory=computer)
             * 组：           (objectCategory=group)
             * 联系人：       (objectCategory=contact)
             * 共享文件夹：   (objectCategory=volume)
             * 打印机         (objectCategory=printQueue)
             * ---------------------------------------------------
             */
            DirectorySearcher mySearcher = new DirectorySearcher(entryOU, "(objectclass=organizationalUnit)"); //查询组织单位                 

            DirectoryEntry root = mySearcher.SearchRoot;   //查找根OU

            SyncRootOU(root);

            StringBuilder sb = new StringBuilder();

            sb.Append("\r\nID\t帐号\t类型\t父ID\r\n");

            foreach (var item in list)
            {
                sb.AppendFormat("{0}\t{1}\t{2}\t{3}\r\n", item.Id, item.Name, item.TypeId, item.ParentId);
            }

        }
        #endregion

        #region## 同步根组织单位
        /// <summary>
        /// 功能: 同步根组织单位
        /// 创建人:Wilson
        /// 创建时间:2012-12-15
        /// </summary>
        /// <param name="entry"></param>
        private void SyncRootOU(DirectoryEntry entry)
        {
            if (entry.Properties.Contains("ou") && entry.Properties.Contains("objectGUID"))
            {
                string rootOuName = entry.Properties["ou"][0].ToString();
                byte[] bGUID = entry.Properties["objectGUID"][0] as byte[];
                string id = BitConverter.ToString(bGUID);
                list.Add(new AdModel(id, rootOuName, (int)TypeEnum.OU, "0", string.Empty, string.Empty, null, string.Empty));
                SyncSubOU(entry, id);
            }
        }
        #endregion

        #region## 同步下属组织单位及下属用户
        /// <summary>
        /// 功能: 同步下属组织单位及下属用户
        /// 创建人:Wilson
        /// 创建时间:2012-12-15
        /// </summary>
        /// <param name="entry"></param>
        /// <param name="parentId"></param>
        private void SyncSubOU(DirectoryEntry entry, string parentId)
        {
            foreach (DirectoryEntry subEntry in entry.Children)
            {
                string entrySchemaClsName = subEntry.SchemaClassName;

                string[] arr = subEntry.Name.Split('=');
                string categoryStr = arr[0];
                string nameStr = arr[1];
                string id = string.Empty;

                if (subEntry.Properties.Contains("objectGUID"))   //SID
                {
                    byte[] bGUID = subEntry.Properties["objectGUID"][0] as byte[];

                    id = BitConverter.ToString(bGUID);
                }
                string accountName = string.Empty;
                string displayname = string.Empty;
                string department = string.Empty;
                string mail = string.Empty;
                List<string> member = new List<string>();
                if (subEntry.Properties.Contains("samaccountName"))
                {
                    accountName = subEntry.Properties["samaccountName"][0].ToString();

                }
                if (subEntry.Properties.Contains("member"))
                {
                    foreach (var m in subEntry.Properties["member"])
                    {
                        member.Add(m.ToString());
                    }
                }
                if (subEntry.Properties.Contains("displayname"))
                {
                    displayname = subEntry.Properties["displayname"][0].ToString();
                }
                if (subEntry.Properties.Contains("mail"))
                {
                    mail = subEntry.Properties["mail"][0].ToString();
                }
                if (subEntry.Properties.Contains("department"))
                {
                    department = subEntry.Properties["department"][0].ToString();
                }
                bool isExist = list.Exists(d => d.Id == id);

                switch (entrySchemaClsName)
                {
                    case "organizationalUnit":
                        if (!isExist)
                        {
                            list.Add(new AdModel(id, nameStr, (int)TypeEnum.OU, parentId, displayname, mail, null, department));
                        }
                        SyncSubOU(subEntry, id);
                        break;
                    case "user":
                        if (!isExist)
                        {
                            list.Add(new AdModel(id, accountName, (int)TypeEnum.USER, parentId, displayname, mail, member, department));
                        }
                        break;
                    case "group":
                        if (!isExist)
                        {
                            list.Add(new AdModel(id, accountName, (int)TypeEnum.GROUP, parentId, displayname, mail, member, department));
                        }
                        break;
                    default:
                        string cls = entrySchemaClsName;
                        break;
                }
            }
        }
        #endregion


        //foreach (string property in subEntry.Properties.PropertyNames)
        //{
        //    LogRecord.WriteLog(string.Format("字段名: {0}   字段值：{1}\r\n", property, subEntry.Properties[property][0].ToString()));
        //}

        #region## 是否连接到域
        /// <summary>
        /// 功能：是否连接到域
        /// 作者：Wilson
        /// 时间：2012-12-15
        /// http://msdn.microsoft.com/zh-cn/library/system.directoryservices.directoryentry.path(v=vs.90).aspx
        /// </summary>
        /// <param name="domainName">域名或IP</param>
        /// <param name="userName">用户名</param>
        /// <param name="userPwd">密码</param>
        /// <param name="entry">域</param>
        /// <returns></returns>
        private bool IsConnected(string domainName, string userName, string userPwd, out DirectoryEntry domain)
        {
            domain = new DirectoryEntry();
            try
            {
                domain.Path = string.Format("LDAP://{0}", domainName);
                domain.Username = userName;
                domain.Password = userPwd;
                domain.AuthenticationType = AuthenticationTypes.Secure;
                domain.RefreshCache();

                return true;
            }
            catch (Exception ex)
            {
                LogHelper.Error("[IsConnected方法]错误信息：" + ex.Message);
                return false;
            }
        }
        #endregion

        #region## 域中是否存在组织单位
        /// <summary>
        /// 功能：域中是否存在组织单位
        /// 作者：Wilson
        /// 时间：2012-12-15
        /// </summary>
        /// <param name="entry"></param>
        /// <param name="ou"></param>
        /// <returns></returns>
        private bool IsExistOU(DirectoryEntry entry, out DirectoryEntry ou, string rootOU)
        {
            ou = new DirectoryEntry();
            try
            {
                ou = entry.Children.Find("OU=" + rootOU.Trim());

                return (ou != null);
            }
            catch (Exception ex)
            {
                LogHelper.Error("[IsExistOU方法]错误信息：" + ex.Message);
                return false;
            }
        }
        #endregion
    }

    public enum TypeEnum : int
    {
        /// <summary>
        /// 组织单位
        /// </summary>
        OU = 1,

        /// <summary>
        /// 用户
        /// </summary>
        USER = 2,
        /// <summary>
        /// 组
        /// </summary>
        GROUP = 3
    }

    #region## Ad域实体
    /// <summary>
    /// Ad域实体
    /// </summary>
    public class AdModel
    {
        public AdModel(string id, string name, int typeId, string parentId, string displayName, string mail, List<string> member, string department)
        {
            Id = id;
            Name = name;
            TypeId = typeId;
            ParentId = parentId;
            DisplayName = displayName;
            Mail = mail;
            Member = member;
            Department = department;
        }
        public string DisplayName { get; set; }
        public string Mail { get; set; }
        public string Id { get; set; }
        public string Department { get; set; }
        public string Name { get; set; }
        public int TypeId { get; set; }
        public List<string> Member { get; set; }
        public string ParentId { get; set; }
    }
    #endregion

}